﻿#region Header
//
//	Project:		AllegroNET
//	Description:	Silverlight port of Allegro (http://alleg.sourceforge.net/)
//
//	Color manipulation routines
//
//	Copyright © 2010 Andrey Gayvoronsky
//
//	Please read the License.txt for details.
//
#endregion

using System;
using System.Windows.Media;

namespace AllegroNET
{
	public partial class Allegro
	{
		public const int MASK_COLOR_8		= 0;
		public const int MASK_COLOR_15		= 0x7C1F;
		public const int MASK_COLOR_16		= 0xF81F;
		public const int MASK_COLOR_24		= 0xFF00FF;
		public const int MASK_COLOR_32		= 0xFF00FF;

		//Allegro uses RGBA order, but Silverlight uses BGRA order
		private const byte RGB_B_SHIFT_15 = 0;
		private const byte RGB_G_SHIFT_15 = 5;
		private const byte RGB_R_SHIFT_15 = 10;
		private const byte RGB_B_SHIFT_16 = 0;
		private const byte RGB_G_SHIFT_16 = 5;
		private const byte RGB_R_SHIFT_16 = 11;
		private const byte RGB_B_SHIFT_24 = 0;
		private const byte RGB_G_SHIFT_24 = 8;
		private const byte RGB_R_SHIFT_24 = 16;

		private const byte RGB_B_SHIFT_32 = 0;
		private const byte RGB_G_SHIFT_32 = 8;
		private const byte RGB_R_SHIFT_32 = 16;
		private const byte RGB_A_SHIFT_32 = 24;

		// lookup table for scaling 5 bit colors up to 8 bits
		protected static byte[] _rgb_scale_5 = new byte[32]
		{
			0,   8,   16,  24,  33,  41,  49,  57,
			66,  74,  82,  90,  99,  107, 115, 123,
			132, 140, 148, 156, 165, 173, 181, 189,
			198, 206, 214, 222, 231, 239, 247, 255
		};

		// lookup table for scaling 6 bit colors up to 8 bits
		protected static byte[] _rgb_scale_6 = new byte[64]
		{
			0,   4,   8,   12,  16,  20,  24,  28,
			32,  36,  40,  44,  48,  52,  56,  60,
			65,  69,  73,  77,  81,  85,  89,  93,
			97,  101, 105, 109, 113, 117, 121, 125,
			130, 134, 138, 142, 146, 150, 154, 158,
			162, 166, 170, 174, 178, 182, 186, 190,
			195, 199, 203, 207, 211, 215, 219, 223,
			227, 231, 235, 239, 243, 247, 251, 255
		};


		/* color_to_int:
		 * Converts C# Color object into the int
		 */
		static public int color_to_int(Color c)
		{
			return (c.A << 24 | c.R << 16 | c.G << 8 | c.B);
		}

		/* int_to_color:
		 * Converts int into the C# Color object
		 */
		static public Color int_to_color(int color)
		{
			var c = color;
			var r = (byte)(c >> 16);
			var g = (byte)(c >> 8);
			var b = (byte)(c);

			return Color.FromArgb(0xff, r, g, b);
		}

		/* makecol_depth:
		 *  Converts R, G, and B values (ranging 0-255) to whatever pixel format
		 *  is required by the specified color depth.
		 */
		static public int makecol_depth(int color_depth, int r, int g, int b)
		{
			switch (color_depth)
			{
				case 8:
					return makecol8(r, g, b);

				case 15:
					return makecol15(r, g, b);

				case 16:
					return makecol16(r, g, b);

				case 24:
					return makecol24(r, g, b);

				case 32:
					return makecol32(r, g, b);
			}

			return 0;
		}

		/* makeacol_depth:
		 *  Converts R, G, B, and A values (ranging 0-255) to whatever pixel format
		 *  is required by the specified color depth.
		 */
		static public int makeacol_depth(int color_depth, int r, int g, int b, int a)
		{
			switch (color_depth)
			{
				case 8:
					return makecol8(r, g, b);

				case 15:
					return makecol15(r, g, b);

				case 16:
					return makecol16(r, g, b);

				case 24:
					return makecol24(r, g, b);

				case 32:
					return makeacol32(r, g, b, a);
			}

			return 0;
		}

		static public int makecol15(int r, int g, int b)
		{
			return (((r >> 3) << RGB_R_SHIFT_15) |
					((g >> 3) << RGB_G_SHIFT_15) |
					((b >> 3) << RGB_B_SHIFT_15));
		}

		static public int makecol16(int r, int g, int b)
		{
			return (((r >> 3) << RGB_R_SHIFT_16) |
					((g >> 2) << RGB_G_SHIFT_16) |
					((b >> 3) << RGB_B_SHIFT_16));
		}

		static public int makecol24(int r, int g, int b)
		{
			return ((r << RGB_R_SHIFT_24) |
					(g << RGB_G_SHIFT_24) |
					(b << RGB_B_SHIFT_24));
		}

		static public int makecol32(int r, int g, int b)
		{
			return ((0xff << RGB_A_SHIFT_32) |
					(r << RGB_R_SHIFT_32) |
					(g << RGB_G_SHIFT_32) |
					(b << RGB_B_SHIFT_32));
		}

		static public int makeacol32(int r, int g, int b, int a)
		{
			return ((a << RGB_A_SHIFT_32) |
					(r << RGB_R_SHIFT_32) |
					(g << RGB_G_SHIFT_32) |
					(b << RGB_B_SHIFT_32));
		}

		/* makecol8: 
		 *  Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color.
		 *  If the global rgb_map table is initialised, it uses that, otherwise
		 *  it searches through the current palette to find the best match.
		 */
		static public int makecol8(int r, int g, int b)
		{
			throw new Exception("8-bit color is not supported");
		}
	}
}
